home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / Libraries / MacPNG Library 1.02 / pngMacSrc 1.02 / PNG Library 0.80 / PNGREAD.C < prev    next >
Text File  |  1996-05-29  |  22KB  |  718 lines

  1.  
  2. /* pngread.c - read a png file
  3.  
  4.    libpng 1.0 beta 2 - version 0.8
  5.    For conditions of distribution and use, see copyright notice in png.h
  6.    Copyright (c) 1995 Guy Eric Schalnat, Group 42, Inc.
  7.    August 20, 1995
  8.    */
  9.  
  10. #define PNG_INTERNAL
  11. #include "png.h"
  12.  
  13. /* initialize png structure for reading, and allocate any memory needed */
  14. void
  15. png_read_init(png_struct *png_ptr)
  16. {
  17.    jmp_buf tmp_jmp;
  18.  
  19.    memcpy(tmp_jmp, png_ptr->jmpbuf, sizeof (jmp_buf));
  20.    memset(png_ptr, 0, sizeof (png_struct));
  21.    memcpy(png_ptr->jmpbuf, tmp_jmp, sizeof (jmp_buf));
  22.  
  23.    png_ptr->zbuf_size = PNG_ZBUF_SIZE;
  24.    png_ptr->zbuf = png_large_malloc(png_ptr, png_ptr->zbuf_size);
  25.    png_ptr->zstream = &(png_ptr->zstream_struct);
  26.    png_ptr->zstream->zalloc = png_zalloc;
  27.    png_ptr->zstream->zfree = png_zfree;
  28.    png_ptr->zstream->opaque = (voidp)png_ptr;
  29.    inflateInit(png_ptr->zstream);
  30.    png_ptr->zstream->next_out = png_ptr->zbuf;
  31.    png_ptr->zstream->avail_out = (uInt)png_ptr->zbuf_size;
  32. }
  33.  
  34. /* read the information before the actual image data. */
  35. void
  36. png_read_info(png_struct *png_ptr, png_info *info)
  37. {
  38.    png_byte chunk_start[8];
  39.    png_uint_32 length;
  40.  
  41.    png_read_data(png_ptr, chunk_start, 8);
  42.    if (memcmp(chunk_start, png_sig, 8))
  43.       png_error(png_ptr, "Not a Png File");
  44.  
  45.    while (1)
  46.    {
  47.       png_uint_32 crc;
  48.  
  49.       png_read_data(png_ptr, chunk_start, 8);
  50.       length = png_get_uint_32(chunk_start);
  51.       png_reset_crc(png_ptr);
  52.       png_calculate_crc(png_ptr, chunk_start + 4, 4);
  53.       if (!memcmp(chunk_start + 4, png_IHDR, 4))
  54.       {
  55.          if (png_ptr->mode != PNG_BEFORE_IHDR)
  56.             png_error(png_ptr, "Out of Place IHDR");
  57.  
  58.          png_handle_IHDR(png_ptr, info, length);
  59.          png_ptr->mode = PNG_HAVE_IHDR;
  60.       }
  61.       else if (!memcmp(chunk_start + 4, png_PLTE, 4))
  62.       {
  63.          if (png_ptr->mode != PNG_HAVE_IHDR)
  64.             png_error(png_ptr, "Missing IHDR");
  65.  
  66. #if !defined(PNG_READ_OPT_PLTE_SUPPORTED)
  67.          if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE)
  68.             png_crc_skip(png_ptr, length);
  69.          else
  70. #else
  71.          {
  72.             png_handle_PLTE(png_ptr, info, length);
  73.          }
  74. #endif
  75.          png_ptr->mode = PNG_HAVE_PLTE;
  76.       }
  77.       else if (!memcmp(chunk_start + 4, png_IDAT, 4))
  78.       {
  79.          png_ptr->idat_size = length;
  80.          png_ptr->mode = PNG_HAVE_IDAT;
  81.          break;
  82.       }
  83.       else if (!memcmp(chunk_start + 4, png_IEND, 4))
  84.       {
  85.          png_error(png_ptr, "No Image in File");
  86.       }
  87. #if defined(PNG_READ_gAMA_SUPPORTED)
  88.       else if (!memcmp(chunk_start + 4, png_gAMA, 4))
  89.       {
  90.          if (png_ptr->mode != PNG_HAVE_IHDR)
  91.             png_error(png_ptr, "Out of Place PLTE");
  92.  
  93.          png_handle_gAMA(png_ptr, info, length);
  94.       }
  95. #endif
  96. #if defined(PNG_READ_sBIT_SUPPORTED)
  97.       else if (!memcmp(chunk_start + 4, png_sBIT, 4))
  98.       {
  99.          if (png_ptr->mode != PNG_HAVE_IHDR)
  100.             png_error(png_ptr, "Out of Place sBIT");
  101.  
  102.          png_handle_sBIT(png_ptr, info, length);
  103.       }
  104. #endif
  105. #if defined(PNG_READ_cHRM_SUPPORTED)
  106.       else if (!memcmp(chunk_start + 4, png_cHRM, 4))
  107.       {
  108.          if (png_ptr->mode != PNG_HAVE_IHDR)
  109.             png_error(png_ptr, "Out of Place cHRM");
  110.  
  111.          png_handle_cHRM(png_ptr, info, length);
  112.       }
  113. #endif
  114. #if defined(PNG_READ_tRNS_SUPPORTED)
  115.       else if (!memcmp(chunk_start + 4, png_tRNS, 4))
  116.       {
  117.          if (png_ptr->mode != PNG_HAVE_IHDR &&
  118.             png_ptr->mode != PNG_HAVE_PLTE)
  119.             png_error(png_ptr, "Out of Place tRNS");
  120.  
  121.          png_handle_tRNS(png_ptr, info, length);
  122.       }
  123. #endif
  124. #if defined(PNG_READ_bKGD_SUPPORTED)
  125.       else if (!memcmp(chunk_start + 4, png_bKGD, 4))
  126.       {
  127.          if (png_ptr->mode != PNG_HAVE_IHDR &&
  128.             png_ptr->mode != PNG_HAVE_PLTE)
  129.             png_error(png_ptr, "Out of Place bKGD");
  130.  
  131.          png_handle_bKGD(png_ptr, info, length);
  132.       }
  133. #endif
  134. #if defined(PNG_READ_hIST_SUPPORTED)
  135.       else if (!memcmp(chunk_start + 4, png_hIST, 4))
  136.       {
  137.          if (png_ptr->mode != PNG_HAVE_PLTE)
  138.             png_error(png_ptr, "Out of Place hIST");
  139.  
  140.          png_handle_hIST(png_ptr, info, length);
  141.       }
  142. #endif
  143. #if defined(PNG_READ_pHYs_SUPPORTED)
  144.       else if (!memcmp(chunk_start + 4, png_pHYs, 4))
  145.       {
  146.          if (png_ptr->mode != PNG_HAVE_IHDR &&
  147.             png_ptr->mode != PNG_HAVE_PLTE)
  148.             png_error(png_ptr, "Out of Place pHYs");
  149.  
  150.          png_handle_pHYs(png_ptr, info, length);
  151.       }
  152. #endif
  153. #if defined(PNG_READ_oFFs_SUPPORTED)
  154.       else if (!memcmp(chunk_start + 4, png_oFFs, 4))
  155.       {
  156.          if (png_ptr->mode != PNG_HAVE_IHDR &&
  157.             png_ptr->mode != PNG_HAVE_PLTE)
  158.             png_error(png_ptr, "Out of Place oFFs");
  159.  
  160.          png_handle_oFFs(png_ptr, info, length);
  161.       }
  162. #endif
  163. #if defined(PNG_READ_tIME_SUPPORTED)
  164.       else if (!memcmp(chunk_start + 4, png_tIME, 4))
  165.       {
  166.          if (png_ptr->mode == PNG_BEFORE_IHDR ||
  167.             png_ptr->mode == PNG_AFTER_IEND)
  168.             png_error(png_ptr, "Out of Place tIME");
  169.  
  170.          png_handle_tIME(png_ptr, info, length);
  171.       }
  172. #endif
  173. #if defined(PNG_READ_tEXt_SUPPORTED)
  174.       else if (!memcmp(chunk_start + 4, png_tEXt, 4))
  175.       {
  176.          if (png_ptr->mode == PNG_BEFORE_IHDR ||
  177.             png_ptr->mode == PNG_AFTER_IEND)
  178.             png_error(png_ptr, "Out of Place tEXt");
  179.  
  180.          png_handle_tEXt(png_ptr, info, length);
  181.       }
  182. #endif
  183. #if defined(PNG_READ_zTXt_SUPPORTED)
  184.       else if (!memcmp(chunk_start + 4, png_zTXt, 4))
  185.       {
  186.          if (png_ptr->mode == PNG_BEFORE_IHDR ||
  187.             png_ptr->mode == PNG_AFTER_IEND)
  188.             png_error(png_ptr, "Out of Place zTXt");
  189.  
  190.          png_handle_zTXt(png_ptr, info, length);
  191.       }
  192. #endif
  193.       else
  194.       {
  195.          if (isupper(chunk_start[4]))
  196.             png_error(png_ptr, "Unknown Critical Chunk");
  197.  
  198.          png_crc_skip(png_ptr, length);
  199.       }
  200.       png_read_data(png_ptr, chunk_start, 4);
  201.       crc = png_get_uint_32(chunk_start);
  202.       if (((crc ^ 0xffffffffL) & 0xffffffffL) !=
  203.          (png_ptr->crc & 0xffffffffL))
  204.          png_error(png_ptr, "Bad CRC value");
  205.    }
  206. }
  207.  
  208. /* optional call to update the users info structure */
  209. void
  210. png_read_update_info(png_struct *png_ptr, png_info *info_ptr)
  211. {
  212.    if (!(png_ptr->row_init))
  213.       png_read_start_row(png_ptr);
  214.    png_read_transform_info(png_ptr, info_ptr);
  215. }
  216.  
  217. /* initialize palette, background, etc, after transformations
  218.    are set, but before any reading takes place.  This allows
  219.    the user to obtail a gamma corrected palette, for example.
  220.    If the user doesn't call this, we will do it ourselves. */
  221. void
  222. png_start_read_image(png_struct *png_ptr)
  223. {
  224.    if (!(png_ptr->row_init))
  225.       png_read_start_row(png_ptr);
  226. }
  227.  
  228. void
  229. png_read_row(png_struct *png_ptr, png_byte *row, png_byte *dsp_row)
  230. {
  231.    int ret;
  232.  
  233.    if (!(png_ptr->row_init))
  234.       png_read_start_row(png_ptr);
  235.  
  236. #if defined(PNG_READ_INTERLACING_SUPPORTED)
  237.    /* if interlaced and we do not need a new row, combine row and return */
  238.    if (png_ptr->interlaced && (png_ptr->transformations & PNG_INTERLACE))
  239.    {
  240.       switch (png_ptr->pass)
  241.       {
  242.          case 0:
  243.             if (png_ptr->row_number & 7)
  244.             {
  245.                if (dsp_row)
  246.                   png_combine_row(png_ptr, dsp_row,
  247.                      png_pass_dsp_mask[png_ptr->pass]);
  248.                png_read_finish_row(png_ptr);
  249.                return;
  250.             }
  251.             break;
  252.          case 1:
  253.             if ((png_ptr->row_number & 7) || png_ptr->width < 5)
  254.             {
  255.                if (dsp_row)
  256.                   png_combine_row(png_ptr, dsp_row,
  257.                      png_pass_dsp_mask[png_ptr->pass]);
  258.                png_read_finish_row(png_ptr);
  259.                return;
  260.             }
  261.             break;
  262.          case 2:
  263.             if ((png_ptr->row_number & 7) != 4)
  264.             {
  265.                if (dsp_row && (png_ptr->row_number & 4))
  266.                   png_combine_row(png_ptr, dsp_row,
  267.                      png_pass_dsp_mask[png_ptr->pass]);
  268.                png_read_finish_row(png_ptr);
  269.                return;
  270.             }
  271.             break;
  272.          case 3:
  273.             if ((png_ptr->row_number & 3) || png_ptr->width < 3)
  274.             {
  275.                if (dsp_row)
  276.                   png_combine_row(png_ptr, dsp_row,
  277.                      png_pass_dsp_mask[png_ptr->pass]);
  278.                png_read_finish_row(png_ptr);
  279.                return;
  280.             }
  281.             break;
  282.          case 4:
  283.             if ((png_ptr->row_number & 3) != 2)
  284.             {
  285.                if (dsp_row && (png_ptr->row_number & 2))
  286.                   png_combine_row(png_ptr, dsp_row,
  287.                      png_pass_dsp_mask[png_ptr->pass]);
  288.                png_read_finish_row(png_ptr);
  289.                return;
  290.             }
  291.             break;
  292.          case 5:
  293.             if ((png_ptr->row_number & 1) || png_ptr->width < 2)
  294.             {
  295.                if (dsp_row)
  296.                   png_combine_row(png_ptr, dsp_row,
  297.                      png_pass_dsp_mask[png_ptr->pass]);
  298.                png_read_finish_row(png_ptr);
  299.                return;
  300.             }
  301.             break;
  302.          case 6:
  303.             if (!(png_ptr->row_number & 1))
  304.             {
  305.                png_read_finish_row(png_ptr);
  306.                return;
  307.             }
  308.             break;
  309.       }
  310.    }
  311. #endif
  312.  
  313.    if (png_ptr->mode != PNG_HAVE_IDAT)
  314.       png_error(png_ptr, "invalid attempt to read row data");
  315.  
  316.    png_ptr->zstream->next_out = png_ptr->row_buf;
  317.    png_ptr->zstream->avail_out = (uInt)png_ptr->irowbytes;
  318.    do
  319.    {
  320.       if (!(png_ptr->zstream->avail_in))
  321.       {
  322.          while (!png_ptr->idat_size)
  323.          {
  324.             png_byte buf[4];
  325.             png_uint_32 crc;
  326.  
  327.             png_read_data(png_ptr, buf, 4);
  328.             crc = png_get_uint_32(buf);
  329.             if (((crc ^ 0xffffffffL) & 0xffffffffL) !=
  330.                (png_ptr->crc & 0xffffffffL))
  331.                png_error(png_ptr, "Bad CRC value");
  332.  
  333.             png_read_data(png_ptr, buf, 4);
  334.             png_ptr->idat_size = png_get_uint_32(buf);
  335.             png_reset_crc(png_ptr);
  336.  
  337.             png_crc_read(png_ptr, buf, 4);
  338.             if (memcmp(buf, png_IDAT, 4))
  339.                png_error(png_ptr, "Not enough image data");
  340.  
  341.          }
  342.          png_ptr->zstream->avail_in = (uInt)png_ptr->zbuf_size;
  343.          png_ptr->zstream->next_in = png_ptr->zbuf;
  344.          if (png_ptr->zbuf_size > png_ptr->idat_size)
  345.             png_ptr->zstream->avail_in = (uInt)png_ptr->idat_size;
  346.          png_crc_read(png_ptr, png_ptr->zbuf, png_ptr->zstream->avail_in);
  347.          png_ptr->idat_size -= png_ptr->zstream->avail_in;
  348.       }
  349.       ret = inflate(png_ptr->zstream, Z_PARTIAL_FLUSH);
  350.       if (ret == Z_STREAM_END)
  351.       {
  352.          if (png_ptr->zstream->avail_out || png_ptr->zstream->avail_in ||
  353.             png_ptr->idat_size)
  354.             png_error(png_ptr, "Extra compressed data");
  355.          png_ptr->mode = PNG_AT_LAST_IDAT;
  356.          break;
  357.       }
  358.       if (ret != Z_OK)
  359.          png_error(png_ptr, "Compression Error");
  360.  
  361.    } while (png_ptr->zstream->avail_out);
  362.  
  363.    if (ret == Z_STREAM_END)
  364.       png_ptr->zlib_finished = 1;
  365.  
  366.    png_ptr->row_info.color_type = png_ptr->color_type;
  367.    png_ptr->row_info.width = png_ptr->iwidth;
  368.    png_ptr->row_info.channels = png_ptr->channels;
  369.    png_ptr->row_info.bit_depth = png_ptr->bit_depth;
  370.    png_ptr->row_info.pixel_depth = png_ptr->pixel_depth;
  371.    png_ptr->row_info.rowbytes = ((png_ptr->row_info.width *
  372.       (png_uint_32)png_ptr->row_info.pixel_depth + 7) >> 3);
  373.  
  374.    if (png_ptr->row_buf[0])
  375.       png_read_filter_row(&(png_ptr->row_info),
  376.          png_ptr->row_buf + 1, png_ptr->prev_row + 1,
  377.          (int)(png_ptr->row_buf[0]));
  378.  
  379.    memcpy(png_ptr->prev_row, png_ptr->row_buf, (png_size_t)png_ptr->rowbytes + 1);
  380.  
  381.    if (png_ptr->transformations)
  382.       png_do_read_transformations(png_ptr);
  383.  
  384. #if defined(PNG_READ_INTERLACING_SUPPORTED)
  385.    /* blow up interlaced rows to full size */
  386.    if (png_ptr->interlaced &&
  387.       (png_ptr->transformations & PNG_INTERLACE))
  388.    {
  389.       if (png_ptr->pass < 6)
  390.          png_do_read_interlace(&(png_ptr->row_info),
  391.             png_ptr->row_buf + 1, png_ptr->pass);
  392.  
  393.       if (dsp_row)
  394.          png_combine_row(png_ptr, dsp_row,
  395.             png_pass_dsp_mask[png_ptr->pass]);
  396.       if (row)
  397.          png_combine_row(png_ptr, row,
  398.             png_pass_mask[png_ptr->pass]);
  399.    }
  400.    else
  401. #endif
  402.    {
  403.       if (row)
  404.          png_combine_row(png_ptr, row, 0xff);
  405.       if (dsp_row)
  406.          png_combine_row(png_ptr, dsp_row, 0xff);
  407.    }
  408.    png_read_finish_row(png_ptr);
  409. }
  410.  
  411. /* read a one or more rows of image data.   If the image is interlaced,
  412.    and png_set_interlace_handling() has been called, the rows need to
  413.    to contain the contents of the rows from the previous pass.  If
  414.    the image has alpha or transparency, and png_handle_alpha() has been
  415.    called, the rows contents must be initialized to the contents of the
  416.    screen.  row holds the actual image, and pixels are placed in it
  417.    as they arrive.  If the image is displayed after each pass, it will
  418.    appear to "sparkle" in.  display_row can be used to display a
  419.    "chunky" progressive image, with finer detail added as it becomes
  420.    available.  If you do not want this "chunky" display, you may pass
  421.    NULL for display_rows.  If you do not want the sparkle display, and
  422.    you have not called png_handle_alpha(), you may pass NULL for rows.
  423.    If you have called png_handle_alpha(), and the image has either an
  424.    alpha channel or a transparency chunk, you must provide a buffer for
  425.    rows.  In this case, you do not have to provide a display_rows buffer
  426.    also, but you may.  If the image is not interlaced, or if you have
  427.    not called png_set_interlace_handling(), the display_row buffer will
  428.    be ignored, so pass NULL to it. */
  429. void
  430. png_read_rows(png_struct *png_ptr, png_byte **row,
  431.    png_byte **display_row, png_uint_32 num_rows)
  432. {
  433.    png_uint_32 i;
  434.    png_byte **rp;
  435.    png_byte **dp;
  436.  
  437.     rp = row;
  438.     dp = display_row;
  439.     for (i = 0; i < num_rows; i++)
  440.     {
  441.         png_byte *rptr;
  442.         png_byte *dptr;
  443.  
  444.         if (rp)
  445.             rptr = *rp;
  446.         else
  447.             rptr = NULL;
  448.         if (dp)
  449.             dptr = *dp;
  450.         else
  451.             dptr = NULL;
  452.         png_read_row(png_ptr, rptr, dptr);
  453.         if (row)
  454.             rp++;
  455.         if (display_row)
  456.             dp++;
  457.     }
  458. }
  459.  
  460. /* read the image.  If the image has an alpha channel or a transparency
  461.     chunk, and you have called png_handle_alpha(), you will need to
  462.    initialize the image to the current image that png will be overlaying.
  463.    Note that png_set_interlace_handling() has no effect on this call.
  464.    You only need to call this function once.  If you desire to have
  465.    an image for each pass of a interlaced image, use png_read_rows() */
  466. void
  467. png_read_image(png_struct *png_ptr, png_byte **image)
  468. {
  469.    png_uint_32 i;
  470.    int pass, j;
  471.    png_byte **rp;
  472.  
  473.    pass = png_set_interlace_handling(png_ptr);
  474.    for (j = 0; j < pass; j++)
  475.    {
  476.       rp = image;
  477.       for (i = 0; i < png_ptr->height; i++)
  478.       {
  479.          png_read_row(png_ptr, *rp, NULL);
  480.          rp++;
  481.       }
  482.    }
  483. }
  484.  
  485. /* read the end of the png file.  Will not read past the end of the
  486.    file, will verify the end is accurate, and will read any comments
  487.    or time information at the end of the file, if info is not NULL. */
  488. void
  489. png_read_end(png_struct *png_ptr, png_info *info)
  490. {
  491.    png_byte chunk_start[8];
  492.    png_uint_32 length;
  493.    png_uint_32 crc;
  494.  
  495.    png_read_data(png_ptr, chunk_start, 4);
  496.    crc = png_get_uint_32(chunk_start);
  497.    if (((crc ^ 0xffffffffL) & 0xffffffffL) !=
  498.       (png_ptr->crc & 0xffffffffL))
  499.       png_error(png_ptr, "Bad CRC value");
  500.  
  501.    do
  502.    {
  503.       png_read_data(png_ptr, chunk_start, 8);
  504.       length = png_get_uint_32(chunk_start);
  505.       png_reset_crc(png_ptr);
  506.       png_calculate_crc(png_ptr, chunk_start + 4, 4);
  507.  
  508.       if (!memcmp(chunk_start + 4, png_IHDR, 4))
  509.       {
  510.          png_error(png_ptr, "invalid chunk after IDAT");
  511.       }
  512.       else if (!memcmp(chunk_start + 4, png_PLTE, 4))
  513.       {
  514.          png_error(png_ptr, "invalid chunk after IDAT");
  515.       }
  516.       else if (!memcmp(chunk_start + 4, png_gAMA, 4))
  517.       {
  518.          png_error(png_ptr, "invalid chunk after IDAT");
  519.       }
  520.       else if (!memcmp(chunk_start + 4, png_sBIT, 4))
  521.       {
  522.          png_error(png_ptr, "invalid chunk after IDAT");
  523.       }
  524.       else if (!memcmp(chunk_start + 4, png_cHRM, 4))
  525.       {
  526.          png_error(png_ptr, "invalid chunk after IDAT");
  527.       }
  528.       else if (!memcmp(chunk_start + 4, png_tRNS, 4))
  529.       {
  530.          png_error(png_ptr, "invalid chunk after IDAT");
  531.       }
  532.       else if (!memcmp(chunk_start + 4, png_bKGD, 4))
  533.       {
  534.          png_error(png_ptr, "invalid chunk after IDAT");
  535.       }
  536.       else if (!memcmp(chunk_start + 4, png_hIST, 4))
  537.       {
  538.          png_error(png_ptr, "invalid chunk after IDAT");
  539.       }
  540.       else if (!memcmp(chunk_start + 4, png_IDAT, 4))
  541.       {
  542.          if (length > 0 || png_ptr->mode != PNG_AT_LAST_IDAT)
  543.             png_error(png_ptr, "too many IDAT's found");
  544.       }
  545.       else if (!memcmp(chunk_start + 4, png_pHYs, 4))
  546.       {
  547.          png_error(png_ptr, "invalid chunk after IDAT");
  548.       }
  549.       else if (!memcmp(chunk_start + 4, png_oFFs, 4))
  550.       {
  551.          png_error(png_ptr, "invalid chunk after IDAT");
  552.       }
  553. #if defined(PNG_READ_tIME_SUPPORTED)
  554.       else if (!memcmp(chunk_start + 4, png_tIME, 4))
  555.       {
  556.          if (png_ptr->mode == PNG_BEFORE_IHDR ||
  557.             png_ptr->mode == PNG_AFTER_IEND)
  558.             png_error(png_ptr, "Out of Place tIME");
  559.  
  560.          if (info)
  561.             png_handle_tIME(png_ptr, info, length);
  562.          else
  563.             png_crc_skip(png_ptr, length);
  564.       }
  565. #endif
  566. #if defined(PNG_READ_tEXt_SUPPORTED)
  567.       else if (!memcmp(chunk_start + 4, png_tEXt, 4))
  568.       {
  569.          if (png_ptr->mode == PNG_BEFORE_IHDR ||
  570.             png_ptr->mode == PNG_AFTER_IEND)
  571.             png_error(png_ptr, "Out of Place tEXt");
  572.  
  573.          if (info)
  574.             png_handle_tEXt(png_ptr, info, length);
  575.          else
  576.             png_crc_skip(png_ptr, length);
  577.       }
  578. #endif
  579. #if defined(PNG_READ_zTXt_SUPPORTED)
  580.       else if (!memcmp(chunk_start + 4, png_zTXt, 4))
  581.       {
  582.          if (png_ptr->mode == PNG_BEFORE_IHDR ||
  583.             png_ptr->mode == PNG_AFTER_IEND)
  584.             png_error(png_ptr, "Out of Place zTXt");
  585.  
  586.          if (info)
  587.             png_handle_zTXt(png_ptr, info, length);
  588.          else
  589.             png_crc_skip(png_ptr, length);
  590.       }
  591. #endif
  592.       else if (!memcmp(chunk_start + 4, png_IEND, 4))
  593.       {
  594.          png_ptr->mode = PNG_AFTER_IEND;
  595.       }
  596.       else
  597.       {
  598.          if (isupper(chunk_start[4]))
  599.             png_error(png_ptr, "Unknown Critical Chunk");
  600.  
  601.          png_crc_skip(png_ptr, length);
  602.       }
  603.       png_read_data(png_ptr, chunk_start, 4);
  604.       crc = png_get_uint_32(chunk_start);
  605.       if (((crc ^ 0xffffffffL) & 0xffffffffL) !=
  606.          (png_ptr->crc & 0xffffffffL))
  607.          png_error(png_ptr, "Bad CRC value");
  608.       if (png_ptr->mode == PNG_AT_LAST_IDAT)
  609.          png_ptr->mode = PNG_AFTER_IDAT;
  610.    } while (png_ptr->mode != PNG_AFTER_IEND);
  611. }
  612.  
  613. /* free all memory used by the read */
  614. void
  615. png_read_destroy(png_struct *png_ptr, png_info *info, png_info *end_info)
  616. {
  617.    int i;
  618.    jmp_buf tmp_jmp;
  619.  
  620.    if (info)
  621.    {
  622. /* I'm not sure I should be freeing this */
  623.       if (info->palette != png_ptr->palette)
  624.          png_free(png_ptr, info->palette);
  625. /* I'm not sure I should be freeing this */
  626. #if defined(PNG_READ_BACKGROUND_SUPPORTED) && defined(PNG_READ_bKGD_SUPPORTED)
  627.       if (info->trans != png_ptr->trans)
  628.          png_free(png_ptr, info->trans);
  629. #endif
  630. /* I'm not sure I should be freeing this */
  631. #if defined(PNG_READ_hIST_SUPPORTED)
  632.       if (info->hist != png_ptr->hist)
  633.          png_free(png_ptr, info->hist);
  634. #endif
  635. #if defined(PNG_READ_tEXt_SUPPORTED) || defined(PNG_READ_zTXt_SUPPORTED)
  636.       for (i = 0; i < info->num_text; i++)
  637.       {
  638.          png_large_free(png_ptr, info->text[i].key);
  639.       }
  640.  
  641.       png_free(png_ptr, info->text);
  642. #endif
  643.       memset(info, 0, sizeof(png_info));
  644.    }
  645.  
  646.    if (end_info)
  647.    {
  648. #if defined(PNG_READ_tEXt_SUPPORTED) || defined(PNG_READ_zTXt_SUPPORTED)
  649.       for (i = 0; i < end_info->num_text; i++)
  650.       {
  651.          png_large_free(png_ptr, end_info->text[i].key);
  652.       }
  653.  
  654.       png_free(png_ptr, end_info->text);
  655. #endif
  656.       memset(end_info, 0, sizeof(png_info));
  657.    }
  658.  
  659.    png_large_free(png_ptr, png_ptr->zbuf);
  660.    png_large_free(png_ptr, png_ptr->row_buf);
  661.    png_large_free(png_ptr, png_ptr->prev_row);
  662. #if defined(PNG_READ_DITHER_SUPPORTED)
  663.    png_large_free(png_ptr, png_ptr->palette_lookup);
  664.    png_free(png_ptr, png_ptr->dither_index);
  665. #endif
  666. #if defined(PNG_READ_GAMMA_SUPPORTED)
  667.    png_free(png_ptr, png_ptr->gamma_table);
  668. #endif
  669. #if defined(PNG_READ_BACKGROUND_SUPPORTED)
  670.    png_free(png_ptr, png_ptr->gamma_from_1);
  671.    png_free(png_ptr, png_ptr->gamma_to_1);
  672. #endif
  673. #if defined(PNG_READ_GAMMA_SUPPORTED)
  674.    if (png_ptr->gamma_16_table)
  675.    {
  676.       for (i = 0; i < (1 << (8 - png_ptr->gamma_shift)); i++)
  677.       {
  678.          png_free(png_ptr, png_ptr->gamma_16_table[i]);
  679.       }
  680.    }
  681. #endif
  682. #if defined(PNG_READ_BACKGROUND_SUPPORTED)
  683.    png_free(png_ptr, png_ptr->gamma_16_table);
  684.    if (png_ptr->gamma_16_from_1)
  685.    {
  686.       for (i = 0; i < (1 << (8 - png_ptr->gamma_shift)); i++)
  687.       {
  688.          png_free(png_ptr, png_ptr->gamma_16_from_1[i]);
  689.       }
  690.    }
  691.    png_free(png_ptr, png_ptr->gamma_16_from_1);
  692.    if (png_ptr->gamma_16_to_1)
  693.    {
  694.       for (i = 0; i < (1 << (8 - png_ptr->gamma_shift)); i++)
  695.       {
  696.          png_free(png_ptr, png_ptr->gamma_16_to_1[i]);
  697.       }
  698.    }
  699.    png_free(png_ptr, png_ptr->gamma_16_to_1);
  700. #endif
  701. #if defined(PNG_READ_BACKGROUND_SUPPORTED)
  702.    png_free(png_ptr, png_ptr->trans);
  703. #endif
  704. #if defined(PNG_READ_DITHER_SUPPORTED)
  705.    png_free(png_ptr, png_ptr->hist);
  706. #endif
  707.    if (!png_ptr->user_palette)
  708.       png_free(png_ptr, png_ptr->palette);
  709.  
  710.    inflateEnd(png_ptr->zstream);
  711.  
  712.    memcpy(tmp_jmp, png_ptr->jmpbuf, sizeof (jmp_buf));
  713.    memset(png_ptr, 0, sizeof (png_struct));
  714.    memcpy(png_ptr->jmpbuf, tmp_jmp, sizeof (jmp_buf));
  715. }
  716.  
  717.  
  718.